/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package consys.social.core.dao;

import org.apache.log4j.Logger;
import org.apache.hadoop.hbase.client.Result;
import java.util.ArrayList;
import java.util.Map;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.client.Delete;
import consys.social.memcached.service.spymemcached.WallPostTranscoder;
import consys.social.core.service.SocialUtils;
import consys.social.core.bo.Entity;
import consys.social.core.bo.WallPost;
import consys.social.memcached.dao.spymemcached.Memcached;
import consys.social.nosql.dao.hbase.HBase;
import java.io.IOException;
import java.util.List;
import org.apache.hadoop.hbase.client.Put;
import static consys.social.nosql.service.hbase.HBaseHelpers.*;

/**
 *
 * @author petan
 */
public class LikeDaoImpl implements LikeDao {

    private Memcached memcached;
    private ThreadLocal<HBase> walls;
    private Logger logger = Logger.getLogger(LikeDaoImpl.class);
    private int storeSeconds;

    public void setMemcached(Memcached memcached) {
        this.memcached = memcached;
    }

    public void setStoreSeconds(int storeSeconds) {
        this.storeSeconds = storeSeconds;
    }

    public void setWalls(ThreadLocal<HBase> walls) {
        this.walls = walls;
    }

    @Override
    public void like(Entity who, WallPost post) throws IOException {
        try {
            byte[] key = SocialUtils.generateReverseKey(post.getAddedBy().getUid(), post.getDate());
            String memcachedKey = SocialUtils.generateKey(post.getAddedBy().getUid(), post.getDate());
            Put put = new Put(key);
            addToPut(put, "likes", who.getUid(), true);
            logger.info("Saving like to HBase");
            if (walls.get().add(put)) {
                long value = walls.get().increment(key, "info", "likesCount", 1);
                //TODO: if null post probably not on wall anymore but for sure we should look into HBase
                WallPost wp = (WallPost) memcached.get(memcachedKey, new WallPostTranscoder());
                if (wp != null) {
                    wp.setLikesCount(value);
                    memcached.replace(memcachedKey, wp, storeSeconds, new WallPostTranscoder());
                }
            }
        } catch (IOException ex) {
            logger.error("HBase problem - cannot like");
            throw ex;
        }

    }

    @Override
    public void unlike(Entity who, WallPost post) throws IOException {
        try {
            byte[] key = SocialUtils.generateReverseKey(post.getAddedBy().getUid(), post.getDate());
            String memcachedKey = SocialUtils.generateKey(post.getAddedBy().getUid(), post.getDate());
            Delete delete = new Delete(key);
            deleteCol(delete, "likes", who.getUid());
            logger.info("Saving unlike to HBase");
            if (walls.get().deleteIfTrue(delete)) {
                long value = walls.get().increment(key, "info", "likesCount", -1);
                //TODO: Similar task as before
                WallPost wp = (WallPost) memcached.get(memcachedKey, new WallPostTranscoder());
                if (wp != null) {
                    wp.setLikesCount(value);
                    memcached.replace(memcachedKey, wp, storeSeconds, new WallPostTranscoder());
                }
            }
        } catch (IOException ex) {
            logger.error("HBase problem - cannot unlike");
            throw ex;
        }
    }

    @Override
    public List<Entity> getLikes(WallPost post) throws IOException {
        byte[] key = SocialUtils.generateReverseKey(post.getAddedBy().getUid(), post.getDate());

        List<Entity> followings = new ArrayList<Entity>();
        Get get = new Get(key);
        addFamilyToGet(get, "likes");
        Result res = null;
        logger.info("Getting likes");
        try {
            res = walls.get().get(get);
        } catch (IOException ex) {
            logger.error("HBase problem - cannot get likes");
            throw ex;
        }
        if (res != null) {
            Map<byte[], byte[]> results = res.getFamilyMap("likes".getBytes());
            if (results != null) {
                for (byte[] oneFollower : results.keySet()) {
                    followings.add(new Entity(Bytes.toString(oneFollower)));
                }
            }
        }
        return followings;
    }
}
